package top.suven.http.oauth.facade;


import com.alibaba.dubbo.config.annotation.Reference;
import top.suven.base.oauth.dto.request.AuthClientInfoRequestDto;
import top.suven.base.oauth.dto.request.OAuthUserRequestDto;
import top.suven.base.oauth.dto.response.OAuthClientInfoResponseDto;
import top.suven.base.oauth.service.OAuthService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import top.suven.base.core.redis.RedisClusterServer;
import top.suven.base.core.redis.RedisConstants;
import top.suven.base.core.redis.RedisKeys;
import top.suven.base.core.redis.RedisUtil;
import top.suven.base.util.utilize.BeanUtil;
import top.suven.http.oauth.vo.OAuthParameter;
import top.suven.http.oauth.vo.OAuthTokenBuilder;
import top.suven.http.oauth.vo.OauthClientDetails;

import java.util.Map;

/**
 * @ClassName OauthServiceFacede
 * @Author suven.wang
 * @Description //TODO ${END}$
 * @CreateDate 2018-09-28  17:13
 * @WeeK 星期五
 * @Version v2.0
 **/

@Component
public class OauthServiceFacade {

    @Reference
    private OAuthService oAuthService;

    @Autowired
    private RedisClusterServer redisClusterServer;


    /**
     * 获取软件申请的client信息;
     * @param clientId
     * @return
     */
    public OauthClientDetails getOauthClientDetailsByClientId(String clientId){
        AuthClientInfoRequestDto requestDto =  AuthClientInfoRequestDto.clientInfo().setClientId(clientId);

        OAuthClientInfoResponseDto responseDto = oAuthService.getAuthClientInfoByClientId(requestDto);
        OauthClientDetails clientDetails = new OauthClientDetails();
        BeanUtil.copyProperties(responseDto,clientDetails);
        clientDetails.setStatus(responseDto.getStatus());
        clientDetails.scope(responseDto.getScopes())
                    .setName(responseDto.getClientName());
        return clientDetails;
    }

    /**
     * 校验用户账号信息, 是否有效,有效返回true,否则为false;
     * @param parameter
     * @return
     */
    public boolean checkUserLoginByRefreshToken(OAuthParameter parameter){
        OAuthUserRequestDto user =  OAuthUserRequestDto.build()
                .setUserId(parameter.getUserId())
                .setToken(parameter.getRefreshToken());
        String refreshKey = RedisUtil.formatKey(RedisKeys.OAUTH_USER_REFRESH_TOKEN_MAP,parameter.getUserId());
        String refreshToken = redisClusterServer.get(refreshKey);
        if(refreshToken.equals(parameter.getRefreshToken())){
            return true;
        }
        return false;
    }

    /**
     * 校验用户账号密码信息, 是否有效,有效返回true,否则为false;
     * @param userName
     * @param password
     * @return
     */
    public long checkUserInfoByNameAndPw(String userName,String password ){
        OAuthUserRequestDto requestDto = OAuthUserRequestDto.build()
                .setUsername(userName)
                .setPassword(password);
        //todo rpc
        if(true){
            return 123456;
        }
        return 0;
    }

    /**
     * 校验用户checkUserCode信息, 是否有效,有效返回true,否则为false;
     * @param parameter
     * @return
     */
    public boolean saveAuthorizationCode(OAuthParameter parameter){
        OAuthUserRequestDto requestDto =  OAuthUserRequestDto.build()
                .setUserId(parameter.getUserId())
                .setCode(parameter.getCode())
                .setClientId(parameter.getClientId())
                .setState(parameter.getState());
        String codeKey = RedisUtil.formatKey(RedisKeys.OAUTH_CODE,requestDto.getUserId(),requestDto.getClientId());
        boolean result =  redisClusterServer.setex(codeKey,requestDto.getCode(),RedisConstants.HALF_HOUR);
        return result;
    }

    /**
     * 校验用户checkUserCode信息, 是否有效,有效返回true,否则为false;
     * @param parameter
     * @return
     */
    public boolean checkAuthorizationCode(OAuthParameter parameter){
        OAuthUserRequestDto requestDto = OAuthUserRequestDto.build()
                .setUserId(parameter.getUserId())
                .setCode(parameter.getCode())
                .setClientId(parameter.getClientId())
                .setState(parameter.getState());
        String codeKey = RedisUtil.formatKey(RedisKeys.OAUTH_CODE,requestDto.getUserId(),requestDto.getClientId());
        String code = redisClusterServer.get(codeKey);
        if(code != null && code.equals(requestDto.getCode())){
            redisClusterServer.del(codeKey);
            return true;
        }
        return false;
    }

    /**
     * 刷新RefreshToken 一个用户仅且只有一个,过期时间为1个月,但token有多少,过期时间为7天
     * 创建token,并更新到缓存中
     * @param oAuthToken
     * @return
     */
    public boolean saveUserToken(OAuthTokenBuilder oAuthToken){
        String codeKey = RedisUtil.formatKey(RedisKeys.OAUTH_USER_ID_TOKEN_MAP,oAuthToken.getUserId());
        String refreshKey = RedisUtil.formatKey(RedisKeys.OAUTH_USER_REFRESH_TOKEN_MAP,oAuthToken.getUserId());
        String refreshToken = redisClusterServer.get(refreshKey);
        if(refreshToken != null){
            oAuthToken.setRefreshToken(refreshToken);
        }
        boolean tokenResult = redisClusterServer.hmset(codeKey,oAuthToken.getAccessToken(),oAuthToken.getExpires());
        boolean refreshResult = redisClusterServer.setex(refreshKey,oAuthToken.getRefreshToken(),RedisConstants.ONE_MONTH);
        if(tokenResult && refreshResult){
            redisClusterServer.expire(codeKey,RedisConstants.SEVEN_DAY);
            return true;
        }
        return false;
    }

    /**
     * 收集用户的原来token,并校验通过后,返回更新后的token,否则返回空;
     * @param oAuthToken
     * @return
     */
    public OAuthTokenBuilder refreshToken(OAuthTokenBuilder oAuthToken){
        String codeKey = RedisUtil.formatKey(RedisKeys.OAUTH_USER_ID_TOKEN_MAP,oAuthToken.getUserId());
        String refreshKey = RedisUtil.formatKey(RedisKeys.OAUTH_USER_REFRESH_TOKEN_MAP,oAuthToken.getUserId());
        String refreshToken = redisClusterServer.get(refreshKey);
        if(null != refreshToken  && refreshToken.equals(oAuthToken.getRefreshToken())){
            //增加token和过期时间
            redisClusterServer.hmset(codeKey,oAuthToken.getAccessToken(),oAuthToken.getExpires());
            redisClusterServer.expire(codeKey,RedisConstants.ONE_HOUR);
            return oAuthToken;
        }
       return null;

    }

    /**
     * 校验用户token信息, 是否有效,有效返回true,否则为false;
     * @param oAuthToken
     * @return
     */
    public boolean checkUserToken(OAuthTokenBuilder oAuthToken){
        String codeKey = RedisUtil.formatKey(RedisKeys.OAUTH_USER_ID_TOKEN_MAP,oAuthToken.getUserId());
        long expire = System.currentTimeMillis();
        Map<String,String> result = redisClusterServer.getMapCacheAndDelExpire(codeKey,expire);
        if(null != result && result.containsKey(oAuthToken.getAccessToken()) ){
            return true;
        }
        return false;
    }


}
